var Fug = (function() {
    var scrList = [],
        cssList =  [],
        helpList = {},
        domHead =  document.getElementsByTagName('head')[0],
        win = window,
        doc = document,
        c = console,
        cl = console.log,
        aConDisplay = true,
        defaultCanvas = null;

console.log('****************');

    var testkit = (function() {
        var queue = [], paused = false, results;

        function _test(value, action) {          
          // if 'value' is not a string, then we're doing a a one off simpe test
          if (typeof value != 'string') {
            results = document.getElementById("results");
            
            // action is just a string
            _assert(value, action);
            return;
          }
        
          queue.push(function() {
            results = document.getElementById("results");
            results = _assert(true, value).appendChild(
                document.createElement("ul"));
            action();
          });
          runTest();
        };
        function _pause() {
          paused = true;
        };
        function _resume() {
          paused = false;
          setTimeout(runTest, 1);
        };
        function runTest() {
          if (!paused && queue.length) {
            (queue.shift())();
            if (!paused) {
              _resume();
            }
          }
        }

        function _assert(value, desc) {
          var li = document.createElement("li");
          
          li.className = value ? "pass" : "fail";
          li.appendChild(document.createTextNode(desc));
          results.appendChild(li);
          if (!value) {
            li.parentNode.parentNode.className = "fail";
          }
          return li;
        };
        
        return {
            test: _test,
            assert: _assert,
            pause: _pause,
            resume: _resume
        }
    } )();
    
    //File system methods - uses the FileSaver/BlobBuilder/canvastoBlob libs
    // note these do not work in FF.. so use Chrome
    var fileSystem = ( function() {
        return {
            saveCurentdocument: function(toFile) {
                // if filename contains a dir struct, it is ignored and a filename
                // constructed as one long string is used to save the file.. always in the
                // Downloads directory
                //
                var bb = new BlobBuilder();
                
                bb.append((new XMLSerializer).serializeToString(document));
                var blob = bb.getBlob("application/xhtml+xml;charset=" + document.characterSet);
                saveAs(blob, toFile);
            },
            saveText: function(text, toFile) {
                saveAs( new BB([text], {type: "text/plain;charset=" + document.characterSet}), toFile);
            },
            
            saveImage: function() {
            },
            
            saveCanvasToFile: function(canvas, toFile) {
                // Firefox - the toFile is ignored and a random filename is generated
                // Chrome - saves it to the toFile
                //
                canvas = canvas || defaultCanvas;

                canvas.toBlob(
                    function(blob) {
                        saveAs(blob, toFile);
                    },
                    "image/png"
                );
            }
        };
        
    } )();
    
    var canvaskit = ( function() {
        return {
            getCanvas: function(domName, width, height) {
                domName = domName || 'myCanvas';
                width = width || 600;
                height = height || 400;
                var canvasElement = _toolkit.addDomEl('canvas', domName, width, height);
                
                defaultCanvas = canvasElement;
                return canvasElement;
            },
            
            getContext: function(canvasElement) {
                canvasElement = canvasElement || defaultCanvas;
                return canvasElement.getContext("2d");
            },
            
            loadImage: function(uri, canvasContext, callback ) {
                canvasContext = canvasContext || defaultCanvas.getContext("2d");
                var img = new Image();
                img.onload = function() { 
                    callback(img, canvasContext); };
                img.src = uri;
                return img;
            },
            
            drawOnCanvas: function(img, canvasContext, x, y) {
                x = x || 0;
                y = y || 0;
                
                canvasContext.canvas.width = img.width;
                canvasContext.canvas.height = img.height;
                canvasContext.drawImage(img, x, y, img.width, img.height);
            },
            
            // Converts canvas to an image
            convertCanvasToImage: function(canvas, callback) {
                var image = new Image();
                img.onload = function() { callback(); };
                image.src = canvas.toDataURL("image/png");
                return image;
            },
            
            wipeCanvas: function(canvasElement) {
                canvasElement.height = canvasElement.height;
            }
        }
    }) ();
    

    var _toolkit =  {
        win: window,    // shortcut to the WINDOW object
        doc: document,  // shortcut to the DOM document object
        c: console,     // shortcut to system console object
        cl: console.log,    // shortcut to system console.log
        
        help: function() {
            // list the functions available in this toolkit
            cl(helpList);
        },
        
        scrExists: function(uri) { return scrList.indexOf(uri) < 0 ? false : true; },
        cssExists: function(uri) { return cssList.indexOf(uri) < 0 ? false : true; },
        
        listResourceFiles: function() {
            var i, defCl;
            
            // list all loaded as part of the document load
            defCl = document.getElementsByTagName("script");
            for (i = 0; i < defCl.length; i++) {
                cl(' Default load SCRIPT: ', defCl[i].src);
            }
            
            defCl = document.getElementsByTagName("link");
            for (i = 0; i < defCl.length; i++) {
                if (domId.rel == 'stylesheet') cl(' Default load CSS: ', defCl[i].href);
            }
            
            
            // list all loaded manually
            for (i = 0; i < scrList.length; i++) {
                cl('Manual load SCRIPT: ', scrList[i]);
            }
            
            for (i = 0; i < cssList.length; i++) {
                cl('Manual load CSS: ', cssList[i]);

            }
            
        },

        domId: function(id) { return document.getElementById(id); },
        domCl: function(tag) { return document.getElementsByTagName(tag); },
        
        // simple method to add a DOM element into the document
        addDomEl: function(tag, id, width, height) {
            var domId = document.createElement(tag);
            domId.id = id;
            domId.style.width = width+'px';
            domId.style.height = height+'px';
            domId.style.border = '1px solid black';
            domId.style.marginTop = '2px';
            document.body.appendChild(domId);
            return domId;
        },
        
        // Inject a script tag into the current document:
        addScript: function(uri) {
            if ( this.scrExists(uri) ) return null;
            
            var domId = document.createElement("script");
            domId.src = uri;
            domHead.appendChild(domId);
            
            scrList.push(uri);
            return { domId: domId, listId: scrList.length-1 };
        },
        
        // add a CSS into the document
        addCSS: function(uri) {
            if ( this.cssExists(uri) ) return null;
            
            var domId = document.createElement("link");
            domId.rel = 'stylesheet';
            domId.type = 'text/css';
            domId.href = uri;
            this.domHead.appendChild(domId);
            
            cssList.push(scr);
            return { domId: domId, listId: cssList.length-1 };
        },
        
        rmvScript: function(ref) {
            ref.domId.parentNode.removeChild(ref.domId);
            scrList.splice(ref.listId, 1);
        },
        
        rmvCSS: function(ref) {
            ref.domId.parentNode.removeChild(ref.domId);
            cssList.splice(ref.listId, 1);
        },
        
        test: testkit.test,
        assert: testkit.assert,
        pause: testkit.pause,
        resume: testkit.resume,
        
        toggleConsole: function() {
            var aCon = document.getElementById("assertConsole");
            aConDisplay = !aConDisplay;
            aCon.style.display = aConDisplay ? 'block' :'none';
        },
                
        ck: canvaskit,
        fs: fileSystem,
        
        startClock: function() {
            var baseTime = (new Date()).getTime();
            return function() { return ((new Date()).getTime() - baseTime); }
        }
    };
    
    for (var p in _toolkit) {
        if (typeof _toolkit[p] == 'function') {
            helpList[p] = p + /(^function\s*)(.*)(\(.*\))/i.exec(_toolkit[p].toString())[3];
        }
    }
    
    return _toolkit;

}) ();